import React, { Component } from 'react';
import { Row, Col, List, Icon, Button, Input, Modal, Select } from 'antd';
import classnames from 'classnames';
import { connect } from 'react-redux';
import { dataEditorAction } from '../redux/actions';
import { DataType as DataTypeModel, BaseType, Field } from './model';
import './DataType.less';

const baseTypes = [BaseType.number, BaseType.string, BaseType.date];

function mapStateToProps(state) {
  return {
    dataTypes: state.dataEditor.dataType
  };
}

function mapDispatchToProps(dispatch) {
  return {
    add: item => dispatch(dataEditorAction.addDataType(item)),
    remove: item => dispatch(dataEditorAction.removeDataType(item)),
    update: (id, item) => dispatch(dataEditorAction.updateDataType(id, item))
  };
}

@connect(
  mapStateToProps,
  mapDispatchToProps
)
class DataType extends Component {
  state = {
    selectedId: undefined,
    newTypeName: undefined,
    newFieldName: undefined,
    addFieldModaVisible: false,
    tempField: Field.create()
  };

  onNewTypeNameChange = event => {
    const { value } = event.target;
    this.setState({
      newTypeName: value
    });
  };

  onNewFieldNameChange = event => {
    const { value } = event.target;
    this.setState({
      newFieldName: value
    });
  };

  deleteType = (event, type) => {
    event.stopPropagation();
    this.props.remove(type);
  };

  createNewType = () => {
    const { newTypeName } = this.state;
    const newTypes = DataTypeModel.create({ name: newTypeName });
    this.props.add(newTypes);
  };

  renderAddFieldModel = type => {
    const { addFieldModaVisible, tempField } = this.state;
    const { dataTypes } = this.props;
    const allTypes = dataTypes
      .concat(baseTypes)
      .filter(item => item.id !== type.id);
    const fieldNameChange = event => {
      const { value } = event.target;
      const newField = tempField.set('name', value);
      this.setState({
        tempField: newField
      });
    };
    const fieldTypeChange = value => {
      const newField = tempField.set('type', value);
      this.setState({
        tempField: newField
      });
    };
    const closeModal = () => {
      this.setState({
        addFieldModaVisible: false
      });
    };
    const addNewField = () => {
      const fields = type.fields.push(tempField);
      const newType = type.set('fields', fields);
      this.props.update(type.id, newType);
      closeModal();
    };
    return (
      <Modal
        title="add field"
        onCancel={closeModal}
        onOk={addNewField}
        visible={addFieldModaVisible}
      >
        <Row>
          <Col span={4}>
            <span>Field name</span>
          </Col>
          <Col span={14}>
            <Input value={tempField.name} onChange={fieldNameChange} />
          </Col>
        </Row>
        <Row>
          <Col span={4}>
            <span>Field type</span>
          </Col>
          <Col span={14}>
            <Select
              value={tempField.type}
              onChange={fieldTypeChange}
              style={{ width: '100%' }}
            >
              {allTypes.map(item => (
                <Select.Option key={item.id} value={item.id}>
                  {item.name}
                </Select.Option>
              ))}
            </Select>
          </Col>
        </Row>
      </Modal>
    );
  };

  renderDetail(type) {
    if (!type) {
      return null;
    }
    const onNameChange = event => {
      const { value } = event.target;
      const newType = type.set('name', value);
      this.props.update(type.id, newType);
    };
    const openModal = () => {
      this.setState({
        addFieldModaVisible: true,
        tempField: Field.create()
      });
    };
    const deleteField = field => {
      const index = type.fields.indexOf(field);
      if (index > -1) {
        const newFields = type.fields.remove(index);
        const newType = type.set('fields', newFields);
        this.props.update(type.id, newType);
      }
    };
    return (
      <>
        <span>Type name</span>
        <Input
          value={type.name}
          onChange={onNameChange}
          style={{ width: 150 }}
        />
        <List
          dataSource={type ? type.fields : []}
          renderItem={field => (
            <List.Item
              actions={[
                <Icon
                  style={{ cursor: 'pointer' }}
                  onClick={() => deleteField(field)}
                  type="delete"
                />
              ]}
            >
              <Row style={{ width: '100%' }}>
                <Col span={8}>
                  <span>{field.name}</span>
                </Col>
                <Col span={8}>
                  <span>{field.type}</span>
                </Col>
              </Row>
            </List.Item>
          )}
        />
        <div>
          <Button onClick={openModal} type="primary">
            Add new field
          </Button>
        </div>
        {this.renderAddFieldModel(type)}
      </>
    );
  }

  render() {
    const { selectedId, newTypeName } = this.state;
    const { dataTypes } = this.props;
    const selectedType = dataTypes.find(type => type.id === selectedId);
    return (
      <Row className="data-type">
        <Col className="data-type-header" span={24}>
          <span>New type</span>
          <Input
            value={newTypeName}
            onChange={this.onNewTypeNameChange}
            style={{ width: 150 }}
          />
          <Button onClick={this.createNewType} type="primary">
            Create
          </Button>
        </Col>
        <Col className="left-content" span={12}>
          <List
            className="list"
            dataSource={dataTypes}
            renderItem={type => (
              <List.Item
                className={classnames('list-item', {
                  selected: type.id === selectedId
                })}
                actions={[
                  <Icon
                    style={{ cursor: 'pointer' }}
                    onClick={event => this.deleteType(event, type)}
                    type="delete"
                  />
                ]}
                onClick={() => {
                  this.setState({ selectedId: type.id });
                }}
              >
                {type.name}
              </List.Item>
            )}
          />
        </Col>
        <Col className="right-content" span={12}>
          {this.renderDetail(selectedType)}
        </Col>
      </Row>
    );
  }
}

export default DataType;
